package com.filldream.fastboot.common.util;

import cn.hutool.core.date.DateUtil;
import com.filldream.fastboot.common.annotation.ModifyContrastAnn;
import com.filldream.fastboot.common.constant.FinalStr;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author RickSun
 * @data 2023-09-11
 * @description 对象工具类
 */
@Slf4j
public class ObjUtil {

    /**
     * 获取资料完整度
     * @param obj   实体类
     * @param ex    必填字段，逗号隔开
     * @return  计算出实体类中必填字段的完整度
     */
    public static String getInfoComplete(Object obj ,String ex){
        String[] split = ex.split(",");
        int exLength = split.length;
        int okLength = 0;

        Field[] fields = obj.getClass().getDeclaredFields();
        for (Field item : fields) {
            item.setAccessible(true);
            String keyName = item.getName();
            if( ex.contains( keyName ) ){
                try {
                    Object keyValue = FieldUtils.readField( item,obj,true);
                    if(ObjectUtils.isNotEmpty( keyValue )){
                        okLength += 1;
                    }
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        }
        return okLength + "/" + exLength;
    }

    public static StringBuffer getModifyCompareLog(Object before,Object after){
        return getModifyCompareLog( before,after,2);
    }

    /**
     * 获取两个对象修改的内容文案
     * @param before   老对象
     * @param after 新对象
     * @param compareType 对比度 1-严格对比 2-after字段为null表示没有修改 3-after字段为null或""表示没有修改
     * @return
     */
    public static StringBuffer getModifyCompareLog(Object before,Object after,Integer compareType){
        StringBuffer stringBuffer = new StringBuffer("");
        try {
            Class<?> beforeClass = before.getClass();

            Class afterClass = after.getClass();
//            Field[] afterFields = afterClass.getDeclaredFields();
            Field[] afterFields = getAllFields(afterClass);
            for (Field item : afterFields) {
                item.setAccessible(true);
                boolean haAnn = item.isAnnotationPresent(ModifyContrastAnn.class);
                if( !haAnn ){
                    continue;
                }

                //获取中文名，获取值
                ModifyContrastAnn ann = item.getAnnotation(ModifyContrastAnn.class);
                Object afterObj = item.get(after);
//                String afterValue = afterObj != null ? afterObj.toString() : "无";
                String afterValue =  fieldToShowString(afterObj,ann.format());
                String viewName = ann.value();

                //查看老的有没有这个字段
                Field beforeField = beforeClass.getDeclaredField(item.getName());
                if (beforeField != null) {
                    beforeField.setAccessible(true);
                    Object beforeObj = beforeField.get(before);
//                    String beforeValue = beforeObj == null ? "无" : beforeObj.toString();
                    String beforeValue = fieldToShowString(beforeObj,ann.format());

                    if( compareType == 2 ){

                        if( afterObj != null && !fieldToString(beforeValue).equals(fieldToString(afterValue))){
                            stringBuffer.append( viewName ).append(":").append( beforeValue ).append(">").append(afterValue).append(" ");
                        }
                    }else if( compareType == 3 ){
                        if( afterObj != null && !afterObj.toString().equals("") && !fieldToString(beforeValue).equals(fieldToString(afterValue))){
                            stringBuffer.append( viewName ).append(":").append( beforeValue ).append(">").append(afterValue).append(" ");
                        }
                    }else if( compareType == 1  ){
                        //严格对比 TODO
                    }
                }
            }
        }catch (Exception e){
            log.info( "GetModifyContrastLog错误:{}",e.getMessage() );
            stringBuffer.append("getModifyContrastLog错误，请及时联系开发人员");
        }
        return stringBuffer;
    }

    /**
     * 此方法用于前后端数字不一样但结果一样的情况转换
     * 例如前端传10,数据库是10.00可视为没有修改
     * @param obj
     * @return
     */
    private static String fieldToString(Object obj){
        if( ObjectUtils.isEmpty( obj ) ){
            return obj.toString();
        }
        if( obj instanceof Number){
            return new BigDecimal(obj.toString()).setScale( 8,BigDecimal.ROUND_HALF_UP ).toString();
        }else if( obj instanceof CharSequence ){
            if( CheckUtil.checkFloat(obj.toString()) || CheckUtil.checkInteger(obj.toString()) ){
                return new BigDecimal(obj.toString()).setScale( 8,BigDecimal.ROUND_HALF_UP ).toString();
            }
        }
        return obj.toString();
    }

    /**
     * 将属性转换为日期
     * @param obj
     * @param format
     * @return
     */
    private static String fieldToShowString(Object obj,String format){
        if(StringUtils.isBlank(format)){
            return obj == null ? "无" : obj.toString();
        }

        if( format.equals(FinalStr.DATE_TIME_YYYY_MM_DD) ||  format.equals(FinalStr.DATE_TIME_YYYY_MM_DD_HH_MM_SS) || format.equals(FinalStr.DATE_TIME_YYYY_MM_DD_HH_MM)){
            return DateUtil.format((Date) obj,format);
        }

        return obj == null ? "无" : obj.toString();
    }

    /**
     * 获取对象Field[]，包含父级的
     * @param clazz
     * @return
     */
    public static Field[] getAllFields(Class<?> clazz) {
        List<Field> fieldList = new ArrayList<>();
        while (clazz != null && !Object.class.equals(clazz)) {
            Field[] declaredFields = clazz.getDeclaredFields();
            for (Field field : declaredFields) {
                if (!fieldList.contains(field)) {
                    fieldList.add(field);
                }
            }
            clazz = clazz.getSuperclass();
        }
        return fieldList.toArray(new Field[0]);
    }

}
